package com.briup.interfaces.impl;

import com.briup.interfaces.*;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * 配置模块的实现类
 */
public class ConfigurationImpl implements Configuration {
    // 准备一个MAP集合用来保存从XML读取的对象
    private Map<String, EnvironmentModule> map = new HashMap<>();
    // 准备一个map集合，保存每一个对象需要的数据
    private Properties properties = new Properties();
    // 因为重写的方法是非静态的，一定会创建对象
    // 可以把xml文件的读取写在构造器中
    public ConfigurationImpl() {
//        System.out.println("构造器执行");
        SAXReader saxReader = new SAXReader();
        Document document = null;
        try {
            document = saxReader.read(ConfigurationImpl.class.getClassLoader().getResourceAsStream("config.xml"));
            // 获取根节点
            Element rootElement = document.getRootElement();
            // 获取第一级子节点
            List<Element> child1 = rootElement.elements();
            for (Element e1 : child1) {
                // 获得第一级子节点的属性Class
                String className = e1.attribute("class").getValue();
                // 使用classname获得class对象
                Class<?> clazz = Class.forName(className);
                // 使用clazz创建对象
                Object o = clazz.newInstance();
                // 类型判断
                EnvironmentModule em = null;
                if (o instanceof EnvironmentModule) {
                    em = (EnvironmentModule) o;
                }
                // 获得第一级标签名字
                String nodeName = e1.getName();
                map.put(nodeName, em);
                // 再遍历,获得第二级子节点
                List<Element> child2 = e1.elements();
                for (Element e2 : child2) {
                    // 输出每个模块中的属性名字和属性值
                    String n1 = e2.getName();
                    String v1 = e2.getText();
                    // 放入到properties中
                    properties.setProperty(n1, v1);
                }
            }
            // 取出map中的元素，一个一个执行对应的方法
            for (EnvironmentModule em :map.values()){
                em.init(properties);
                em.setConfiguration(this);
            }
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }

    }

    @Test
    public void test1() {
//        new ConfigurationImpl();
    }


    @Override
    public Gather getGather() {
        return (Gather) map.get("gather");
    }

    @Override
    public Client getClient() {
        return (Client) map.get("client");
    }

    @Override
    public Server getServer() {
        return (Server) map.get("server");
    }

    @Override
    public DbStore getDbStore() {
        return (DbStore) map.get("dbStore");
    }

    @Override
    public Log getLog() {
        return (Log) map.get("log");
    }

    @Override
    public Backup getBackup() {
        return (Backup) map.get("backUp");
    }
}
